﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using System.Data.Entity;

namespace ConsoleApp1
{
    public class OrderService
    {
        public OrderService()
        {
            using (var ctx = new OrderContext())
            {
                if (ctx.Goods.Count() == 0)
                {
                    ctx.Goods.Add(new Goods("apple", 100));
                    ctx.Goods.Add(new Goods("egg", 200));
                    ctx.SaveChanges();
                }
                if (ctx.Customers.Count() == 0)
                {
                    ctx.Customers.Add(new Customer("Alice"));
                    ctx.Customers.Add(new Customer("Bob"));
                    ctx.SaveChanges();
                }
            }
        }
        public List<Order> AllOrder
        {
            get
            {
                using (var ctx = new OrderContext())
                {
                    return ctx.Orders.Include(o => o.Details.Select(d=>d.goods))
            .Include(o => o.Customer)
            .ToList();
                }
            }
        }

        //新增订单
        public void AddOrder(Order order)
        {
            FixOrder(order);
            using (var ctx = new OrderContext())
            {
                ctx.Entry(order).State = EntityState.Added;
                ctx.SaveChanges();
            }
        }
        public void AddOrder(Customer c, List<OrderDetail> details, Time time)
        {
            Order order = new Order(c,details, time);
            AddOrder(order);
        }
        //删除订单
        public void RemoveOrder(List<Order> orders)
        {
            if (Search(orders).Count == 0) throw new NotFoundException("Order with this ID is not found!");
            Search(orders).ForEach(o => { AllOrder.Remove(o); Order.number--; });              
        }
        public void RemoveOrder(string ID)
        {
            using (var ctx = new OrderContext())
            {
                var order = ctx.Orders.Include("Details")
                  .SingleOrDefault(o => o.ID == ID);
                if (order == null) return;
                ctx.OrderDetails.RemoveRange(order.Details);
                ctx.Orders.Remove(order);
                ctx.SaveChanges();
            }
        }

        //修改订单
        public void modifyOrder(string ID, Customer c)
        {
            var query = AllOrder.Where(o => o.ID == ID);
            if (query.ToList().Count == 0) throw new NotFoundException("Order with this ID is not found!");
            if (query.ToList().Count > 1) throw new RepleteException("Order with this ID is more than one!");
            query.ToList()[0]=modify(query.ToList()[0],c);
        }
        public void modifyOrder(string ID, List<OrderDetail> details)
        {
            var query = AllOrder.Where(o => o.ID == ID);
            if (query.ToList().Count == 0) throw new NotFoundException("Order with this ID is not found!");
            if (query.ToList().Count > 1) throw new RepleteException("Order with this ID is more than one!");
            query.ToList()[0] = modify(query.ToList()[0], details);
        }

        public void modifyOrder(string ID, Time t)
        {
            var query = AllOrder.Where(o => o.ID == ID);
            if (query.ToList().Count == 0) throw new NotFoundException("Order with this ID is not found!");
            if (query.ToList().Count > 1) throw new RepleteException("Order with this ID is more than one!");
            query.ToList()[0] = modify(query.ToList()[0], t);
        }
        public Order modify(Order order, Customer c)
        {
            order.setCustomer(c);
            return order;
        }
        public Order modify(Order order, List<OrderDetail>details)
        {
            order = new Order(order.GetCustomer(), details, order.GetTime());
            return order;
        }
        public Order modify(Order order, Time t)
        {
            order.setTime(t);
            return order;
        }


        //查询订单
        public List<Order> Search(string[] orderID) {
            
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => orderID.Contains(o.ID)).OrderBy(o => o.Amount)
                  .ToList();
            }
        }
        public List<Order> Search(string orderID)
        {
            
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => orderID == o.ID).OrderBy(o => o.Amount)
                  .ToList();
            }
        }
        public List<Order> Search(OrderDetail detail)
        {
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => o.GetOrderDetails().Where(d => d.goods.Name == detail.goods.Name).Count() == 1).OrderBy(o => o.Amount)
                  .ToList();
            }

        }
        public List<Order> Search(Customer c)
        {
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => o.GetCustomer().getName().Equals(c.getName())).OrderBy(o => o.Amount)
                  .ToList();
            }
        }

        public List<Order> Search(List<Order> orders)
        {
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => orders.Contains(o)).OrderBy(o => o.Amount)
                  .ToList();
            }
        }
        //查找所有总金额超过某个金额的订单
        public List<Order>Search(double amount1)
        {
            using (var ctx = new OrderContext())
            {
                return ctx.Orders
                  .Include(o => o.Details.Select(d => d.goods))
                  .Include(o => o.Customer)
                  .Where(o => o.Amount - amount1 >= 0).OrderBy(o => o.Amount)
                  .ToList();
            }
        }
        public void UpdateOrder(Order newOrder)
        {
            RemoveOrder(newOrder.ID);
            AddOrder(newOrder);
        }

        //订单按订单ID排序或自定义排序

        public void Sort()
        {
            AllOrder.Sort((s1, s2) => s1.ID.CompareTo(s2.ID));
        }

        public void Sort(IComparer<Order>comparer)
        {
            AllOrder.Sort(comparer);
        }
        private static void FixOrder(Order newOrder)
        {
            newOrder.Customer = null;
            newOrder.Details.ForEach(d => {
                d.GoodsPrice = d.goods.getPrice().ToString();
                d.goods = null;
            });
        }

        public void Export(String fileName)
        {
            XmlSerializer xs = new XmlSerializer(typeof(List<Order>));
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                xs.Serialize(fs, AllOrder);
            }
        }

        public void Import(string path)
        {
            XmlSerializer xs = new XmlSerializer(typeof(List<Order>));
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                using (var ctx = new OrderContext())
                {
                    List<Order> temp = (List<Order>)xs.Deserialize(fs);
                    temp.ForEach(order => {
                        if (ctx.Orders.SingleOrDefault(o => o.ID == order.ID) == null)
                        {
                            //FixOrder(order);
                            ctx.Orders.Add(order);
                        }
                    });
                    ctx.SaveChanges();
                }
            }
        }
    }
    public class NotFoundException : Exception
    {
        public NotFoundException(string message):base(message)
        {
        }
    }

    public class RepleteException : Exception
    {
        public RepleteException(string message) : base(message)
        {

        }
    }
}
